﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IbsysII.Domain;
using IbsysII.Util;

namespace IbsysII.Service
{
    /// <summary>
    /// Die Service-Klasse kuemmert sich allgemein um das Thema der Zeitverwaltung
    /// </summary>
    public class Zeitverwaltung
    {
        public const int SCHICHT_LAENGE = 2400;

        /// <summary>
        /// speichert die Zuordnung Arbeitsplatz, und deren in Anspruchnahme
        /// </summary>
        public static Dictionary<int, ZeitverwaltungUtil> dicZeitverwaltung = new Dictionary<int, ZeitverwaltungUtil>();
        
        /// <summary>
        /// das Dictionary, welches die Fertigungs- und Ruestzeiten speichert, liest die Informationen ueber die AP aus
        /// und setzt die Fertiguns- und Ruestzeiten auf 0
        /// </summary>
        public static void initDictionary()
        {
            int arbeitsplatzNr = 1;
            foreach (var arbeitsplatz in App.arbeitsplaetze)
	        {
                dicZeitverwaltung.Add(arbeitsplatzNr, new ZeitverwaltungUtil(arbeitsplatz.ArbeitsplatzNr, 
                    App.warteliste.Where(w => w.WartelisteArbeitsplatz == arbeitsplatzNr).Sum(w => w.WartelisteZeitbedarf),
                    App.bearbeitung.Where(b => b.BearbeitungArbeitsplatz == arbeitsplatzNr).Sum(b => b.BearbeitungZeitbedarf), "1", 0));
                arbeitsplatzNr++;
            }
        }

        /// <summary>
        /// Die Zeit wird hier erfasst für ein Produktionsauftrag
        /// </summary>
        /// <param name="teilNummer">Teilnummer zur Identifikation</param>
        /// <param name="menge">Anzahl der Produktionsmenge</param>
        public static void produziereElement(int teilNummer, int menge)
        {
            for (int i = 0; i < App.alleProdukte.Count; i++)
            {
                for (int j = 0; j < App.alleProdukte[i].Count; j++)
                {
                    if (App.alleProdukte[i][j].TeilNr == teilNummer)
                    {
                        Console.WriteLine("Produkt: " + App.alleProdukte[i][j].Bezeichnung);
                        for (int g = 0; g < App.alleProdukte[i][j].lstArbeitschritt.Count; g++)
                        {
                            Console.WriteLine("\tAP-Nr." + App.alleProdukte[i][j].lstArbeitschritt[g].Arbeitsplatz.ArbeitsplatzNr + ": Ruest: " + App.alleProdukte[i][j].lstArbeitschritt[g].Ruestzeit + " Fert: " + App.alleProdukte[i][j].lstArbeitschritt[g].Fertigungszeit);
                            if (App.alleProdukte[i][j].lstArbeitschritt[g].Arbeitsplatz.ArbeitsplatzNr == 1 || App.alleProdukte[i][j].lstArbeitschritt[g].Arbeitsplatz.ArbeitsplatzNr == 2 || App.alleProdukte[i][j].lstArbeitschritt[g].Arbeitsplatz.ArbeitsplatzNr == 3)
                            {
                                dicZeitverwaltung[App.alleProdukte[i][j].lstArbeitschritt[g].Arbeitsplatz.ArbeitsplatzNr] =
                                dicZeitverwaltung[App.alleProdukte[i][j].lstArbeitschritt[g].Arbeitsplatz.ArbeitsplatzNr].addiereZeit(2 * App.alleProdukte[i][j].lstArbeitschritt[g].Ruestzeit, App.alleProdukte[i][j].lstArbeitschritt[g].Fertigungszeit * menge);
                            }
                            else
                            {
                                dicZeitverwaltung[App.alleProdukte[i][j].lstArbeitschritt[g].Arbeitsplatz.ArbeitsplatzNr] =
                                    dicZeitverwaltung[App.alleProdukte[i][j].lstArbeitschritt[g].Arbeitsplatz.ArbeitsplatzNr].addiereZeit(App.alleProdukte[i][j].lstArbeitschritt[g].Ruestzeit, App.alleProdukte[i][j].lstArbeitschritt[g].Fertigungszeit * menge);
                            }
                        }
                        //Methode verlassen, verhindern das Gleichteile mehrmals aufgenommen werden
                        return;
                    }
                }
            }
        }

        /// <summary>
        /// Ausgabe der verbrauchten Minuten pro Arbeitsplatz
        /// </summary>
        public static void gesamtZeit()
        {
            foreach (var zeitItem in dicZeitverwaltung)
            {
                Console.WriteLine("AP: " + zeitItem.Key + " Fertigung: " + zeitItem.Value.Fertigungszeit + " Ruestzeit: " + zeitItem.Value.Ruestzeit);
            }
        }

        /// <summary>
        /// Hier werden pro AP die Schichten sowie die Ueberminuten geplant
        /// </summary>
        public static void finaleZeitberechnung()
        {
            int minuten = 0;
            double kostenNormal = 0.0;
            double kostenUeberstunden = 0.0;
            int ueberMinuten = 0;
            string schicht = "";
            for (int apNr = 1; apNr <= dicZeitverwaltung.Count; apNr++)
            {
                minuten = Convert.ToInt32(dicZeitverwaltung[apNr].Fertigungszeit + dicZeitverwaltung[apNr].Ruestzeit);
                if (minuten > 2.5 * SCHICHT_LAENGE)
                {
                    //kostenNormal = (minuten > 3 * SCHICHT_LAENGE ? 3 * SCHICHT_LAENGE : minuten) * zeitItem.Value.Arbeitsplatz.lstStammdatenSchicht[0].StammLohnDritteSchicht;
                    ueberMinuten = 0;
                    schicht = "3";
                }
                else if (minuten > 1.5 * SCHICHT_LAENGE && minuten <= 2.5 * SCHICHT_LAENGE)
                {
                    //kostenNormal = 2 * SCHICHT_LAENGE * zeitItem.Value.Arbeitsplatz.lstStammdatenSchicht[0].StammLohnZweiteSchicht;
                    ueberMinuten = (minuten - 2 * SCHICHT_LAENGE > 0 ? minuten - 2 * SCHICHT_LAENGE : 0);
                    //kostenUeberstunden = ueberMinuten * zeitItem.Value.Arbeitsplatz.lstStammdatenSchicht[0].StammLohnUeberstunden;
                    schicht = "2";
                }
                else if (minuten <= 1.5 * SCHICHT_LAENGE)
                {
                    //kostenNormal = SCHICHT_LAENGE * zeitItem.Value.Arbeitsplatz.lstStammdatenSchicht[0].StammLohnErsteSchicht;
                    ueberMinuten = (minuten - SCHICHT_LAENGE > 0 ? minuten - SCHICHT_LAENGE : 0);
                    //kostenUeberstunden = ueberMinuten * zeitItem.Value.Arbeitsplatz.lstStammdatenSchicht[0].StammLohnUeberstunden;
                    schicht = "1";
                }
                Console.WriteLine("AP: " + apNr + " Schicht: " + schicht + " Minuten: " + minuten + " Kosten: " + (kostenNormal + kostenUeberstunden) + " Überminuten: " + ueberMinuten);
                dicZeitverwaltung[apNr] = dicZeitverwaltung[apNr].aendereSchicht(schicht);
                dicZeitverwaltung[apNr] = dicZeitverwaltung[apNr].aendereUeberminuten(ueberMinuten);
            }
        }

        public static void berechneZeiten(List<Produktionsauftrag> listAuftraege)
        {
            foreach (var auftrag in listAuftraege)
            {
                produziereElement(auftrag.Teil.TeilNr, auftrag.Teil.Bedarf);
            }
        }


        /// <summary>
        /// interne Specherstruktur fuer die Zeitplanung
        /// Struct, da es sich um einen Werttypen handelt
        /// </summary>
        public struct ZeitverwaltungUtil
        {
            private int arbeitsplatzNr;
            
            public int ArbeitsplatzNr
            {
                get { return arbeitsplatzNr; }
                set { arbeitsplatzNr = value; }
            }
            private int fertigungszeit;

            public int Fertigungszeit
            {
                get { return fertigungszeit; }
                set { fertigungszeit = value; }
            }
            private int ruestzeit;

            public int Ruestzeit
            {
                get { return ruestzeit; }
                set { ruestzeit = value; }
            }

            private string schicht;

            public string Schicht
            {
                get { return schicht; }
                set { schicht = value; }
            }

            private int ueberminuten;

            public int Ueberminuten
            {
                get { return ueberminuten; }
                set { ueberminuten = value; }
            }

         //   private int gesamt;

            public int Gesamt
            {
                get { return ruestzeit + fertigungszeit; }
              //  set { gesamt = value; }
            }


            public ZeitverwaltungUtil(int ap,int fert, int ruest, string schicht, int uebermin)
            {
                arbeitsplatzNr = ap;
                fertigungszeit = fert;
                ruestzeit = ruest;
                this.schicht = schicht;
                ueberminuten = uebermin;
            }

            public ZeitverwaltungUtil addiereZeit(int ruest, int fert)
            {
                this.fertigungszeit += fert;
                this.ruestzeit += ruest;
                return this;
            }

            public ZeitverwaltungUtil aendereSchicht(string schicht)
            {
                this.schicht = schicht;
                return this;
            }

            public ZeitverwaltungUtil aendereUeberminuten(int ueberminuten)
            {
                this.ueberminuten = ueberminuten;
                return this;
            }
        }
    }
}